﻿using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Rabc.Project.Repositories;
using Rbac.Domain;
using Rbac.Project.Application.Menus.Dto;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace Rbac.Project.Application.Menus
{
    public class MenuService : IMenuService
    {
        private readonly IRepository<Menu> repository;
        private readonly IRepository<RoleMenu> repository1;
        private readonly IMapper mapper;
        private readonly IHttpContextAccessor httpContext;

        public MenuService(
            IRepository<Menu> repository,
            IRepository<RoleMenu> repository1,
            IMapper mapper, 
            IHttpContextAccessor httpContext
            )
        {
            this.repository = repository;
            this.repository1 = repository1;
            this.mapper = mapper;
            this.httpContext = httpContext;
        }

        public async Task<ResultDto<List<TreeDto>>> GetTreeNodes()
        {
            var headers = httpContext.HttpContext.Request.Headers;

            var user = httpContext.HttpContext.User.Identity.Name;

            var isLogin = httpContext.HttpContext.User.Identity.IsAuthenticated;

            var claims = httpContext.HttpContext.User.Identities.First().Claims;

            var list = await repository.QueryAsync();
            return new ResultDto<List<TreeDto>> { Code = Result.Success, Data = GetTrees(list, 0) };
        }


        private List<TreeDto> GetTrees(List<Menu> menus, int ParentId)
        {
            List<TreeDto> tree = new List<TreeDto>();

            var list = menus.Where(m => m.ParentId == ParentId);

            foreach (var item in list)
            {
                var treeDto = mapper.Map<TreeDto>(item);
                treeDto.Child = !GetTrees(menus, item.MenuId).Any() ? null : GetTrees(menus, item.MenuId);

                tree.Add(treeDto);
            }

            return tree;
        }

        /// <summary>
        /// 菜单添加
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ResultDto<bool>> InsertAsync(CreateUpdateDto dto)
        {
            try
            {
                await repository.InsertAsync(mapper.Map<Menu>(dto));
                return new ResultDto<bool> { Code = Result.Success, Data = true };
            }
            catch (Exception e)
            {
                return new ResultDto<bool> { Code = Result.Failure, Data = false };
            }            
        }

        public async Task<ResultDto<List<MenuDto>>> GetMenu()
        {
            IEnumerable<Claim> claims = httpContext.HttpContext.User.Claims;

            int[] roleid = Array.ConvertAll(claims.First(m => m.Type == ClaimTypes.Role).Value.Split(','), m => Convert.ToInt32(m));
            
            var list =  await (from a in repository.Queryable()
                        join b in repository1.Queryable() on a.MenuId equals b.MenuID
                        where roleid.Contains(b.RoleID)
                        select a).Distinct().ToListAsync();

            return new ResultDto<List<MenuDto>> { Code = Result.Success,Data = mapper.Map<List<MenuDto>>(list) };
        }
    }
}
